home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / drivers / jrcrypt.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  14KB  |  555 lines

  1. /***************************************************************************
  2.  
  3.   jrcrypt.c
  4.  
  5.   This file is not part of MAME. It is here to provide detailed
  6.   documentation of the encryption used by Jr. Pac Man ROMs.
  7.  
  8.     David Caldwell 6-1-97
  9.     bug reports and comments to:
  10.     david@indigita.com
  11.  
  12.     This code is published under the GNU Public License. (GPL)
  13.  
  14. ***************************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include "mame.h"
  21. #include "driver.h"
  22. #include "osdepend.h"
  23.  
  24. static int interrupt_enable;
  25.  
  26. typedef unsigned short word;
  27. typedef unsigned char byte;
  28.  
  29. #define PreDecryptedRoms
  30.  
  31. #ifndef PreDecryptedRoms
  32. static int s0,s1,s2,s3; /* 1 bit registers inside decoder PAL */
  33. static unsigned char shadowROM[0xffff];
  34. static unsigned char used[0xFFFF];
  35. unsigned long numberUsed = 0;
  36. #else
  37. struct {
  38.     int count;
  39.     int value;
  40. } Jr_PacManTable[] = {
  41.     { 0x00C1, 0x00 },
  42.     { 0x0002, 0x80 },
  43.     { 0x0004, 0x00 },
  44.     { 0x0006, 0x80 },
  45.     { 0x0003, 0x00 },
  46.     { 0x0002, 0x80 },
  47.     { 0x0009, 0x00 },
  48.     { 0x0004, 0x80 },
  49.     { 0x9968, 0x00 },
  50.     { 0x0001, 0x80 },
  51.     { 0x0002, 0x00 },
  52.     { 0x0001, 0x80 },
  53.     { 0x0009, 0x00 },
  54.     { 0x0002, 0x80 },
  55.     { 0x0009, 0x00 },
  56.     { 0x0001, 0x80 },
  57.     { 0x00AF, 0x00 },
  58.     { 0x000E, 0x04 },
  59.     { 0x0002, 0x00 },
  60.     { 0x0004, 0x04 },
  61.     { 0x001E, 0x00 },
  62.     { 0x0001, 0x80 },
  63.     { 0x0002, 0x00 },
  64.     { 0x0001, 0x80 },
  65.     { 0x0002, 0x00 },
  66.     { 0x0002, 0x80 },
  67.     { 0x0009, 0x00 },
  68.     { 0x0002, 0x80 },
  69.     { 0x0009, 0x00 },
  70.     { 0x0002, 0x80 },
  71.     { 0x0083, 0x00 },
  72.     { 0x0001, 0x04 },
  73.     { 0x0001, 0x01 },
  74.     { 0x0001, 0x00 },
  75.     { 0x0002, 0x05 },
  76.     { 0x0001, 0x00 },
  77.     { 0x0003, 0x04 },
  78.     { 0x0003, 0x01 },
  79.     { 0x0002, 0x00 },
  80.     { 0x0001, 0x04 },
  81.     { 0x0003, 0x01 },
  82.     { 0x0003, 0x00 },
  83.     { 0x0003, 0x04 },
  84.     { 0x0001, 0x01 },
  85.     { 0x002E, 0x00 },
  86.     { 0x0078, 0x01 },
  87.     { 0x0001, 0x04 },
  88.     { 0x0001, 0x05 },
  89.     { 0x0001, 0x00 },
  90.     { 0x0001, 0x01 },
  91.     { 0x0001, 0x04 },
  92.     { 0x0002, 0x00 },
  93.     { 0x0001, 0x01 },
  94.     { 0x0001, 0x04 },
  95.     { 0x0002, 0x00 },
  96.     { 0x0001, 0x01 },
  97.     { 0x0001, 0x04 },
  98.     { 0x0002, 0x00 },
  99.     { 0x0001, 0x01 },
  100.     { 0x0001, 0x04 },
  101.     { 0x0001, 0x05 },
  102.     { 0x0001, 0x00 },
  103.     { 0x0001, 0x01 },
  104.     { 0x0001, 0x04 },
  105.     { 0x0002, 0x00 },
  106.     { 0x0001, 0x01 },
  107.     { 0x0001, 0x04 },
  108.     { 0x0002, 0x00 },
  109.     { 0x0001, 0x01 },
  110.     { 0x0001, 0x04 },
  111.     { 0x0001, 0x05 },
  112.     { 0x0001, 0x00 },
  113.     { 0x01B0, 0x01 },
  114.     { 0x0001, 0x00 },
  115.     { 0x0002, 0x01 },
  116.     { 0x00AD, 0x00 },
  117.     { 0x0031, 0x01 },
  118.     { 0x005C, 0x00 },
  119.     { 0x0005, 0x01 },
  120.     { 0x604E, 0x00 },
  121.     { 0,0 }
  122. };
  123. #endif
  124.  
  125. void jrpacman_init_machine(void)
  126. {
  127. #ifndef PreDecryptedRoms
  128.     s0 = 1;
  129.     s1 = 1;
  130.     s2 = 0;
  131.     s3 = 0;
  132.  
  133.     memset(shadowROM,0,sizeof(shadowROM));
  134.     memset(used,0,sizeof(used));
  135. #endif
  136. }
  137.  
  138.  
  139. #ifdef PreDecryptedRoms
  140. unsigned jrpacman_decode_roms(int address)
  141. {
  142.     int i;
  143.     int cumulative=0;
  144.     for (i=0;Jr_PacManTable[i].count;i++)
  145.     {
  146.         cumulative += Jr_PacManTable[i].count;
  147.         if (cumulative > address)
  148.             return RAM[address] ^ Jr_PacManTable[i].value;
  149.     }
  150.     return RAM[address]; // this should never happen!
  151. }
  152. #else
  153. inline WordBit(word theWord, int theBit)
  154. {
  155.     return (theWord >> theBit)&1;
  156. }
  157. inline ByteBit(byte theByte, int theBit)
  158. {
  159.     return (theByte >> theBit)&1;
  160. }
  161.  
  162. int jrpacman_romdecode(int offset);
  163. int jrpacman_romdecodeA(int offset)
  164. {
  165.     jrpacman_romdecode(offset);
  166. }
  167.  
  168. int jrpacman_romdecodeB(int offset)
  169. {
  170.     jrpacman_romdecode(offset + 0x8000);
  171. }
  172.  
  173.  
  174. /****************************************************************************
  175.  
  176.     This function would look suprisingly similiar to the source code to
  177. the encoder pals, I imagine. I wrote is based on the jedec file that I
  178. got from VideoDoctor. It needs to be run during the game, since the
  179. logic is kind of wierd and state based. This is slow. So you'll see
  180. that I made it store its "decrypted" opcodes in another array. When I
  181. ran the program and was satisfied that it had decrypted enough code, I
  182. dumped this new array out into some ROM files.  These ROM files are
  183. effectively decrypted. But nobody else has them, so I'd have to upload
  184. them to some ROM archive somewhere and hope for the best. Besides, If
  185. I ever found a bug in them its not easy to upgrade every ROM archive
  186. site out there. So I created a table that has the decrypted ROMs and
  187. the encrypted ROMs xor-ed with each other.  So if something wrong is
  188. ever discovered , all that is needed to update is the table.  Jr. Pac
  189. only messes with 3 bits (d0, d2 and d7) so the table doesn't look too
  190. excited.  Also I run length encoded it so its not unwieldly.
  191.  
  192.     A lot of the functions that are ifdef-ed out here were debugging
  193. functions that I used to help me during the decoding process.
  194.  
  195.  -David Caldwell
  196.  david@indigita.com
  197.  
  198. ***************************************************************************/
  199.  
  200. #ifdef MACINTOSH
  201. #include <events.h> // for tickcount
  202. #endif
  203.  
  204. int jrpacman_romdecode(int offset)
  205. {
  206.     int addressBus = offset;
  207.     Z80_Regs Regs;
  208.     Z80_GetRegs(&Regs);
  209.  
  210.     {
  211.     int m1 = !Regs.M1;//active low (supposedly means opcode read)
  212.  
  213.     /* Pal 8C (16L8) */
  214.     int pcbe =  !(addressBus >= 0x0000 && addressBus <= 0x3fff ||
  215.                   addressBus >= 0x8000 && addressBus <=
  216. 0xdfff);
  217.  
  218.     int sop0 =  !(addressBus >= 0x0000 && addressBus <= 0x001f ||
  219.                   addressBus >= 0x00e0 && addressBus <=
  220. 0x00ff ||
  221.                   addressBus >= 0x9a60 && addressBus <=
  222. 0x9a7f ||
  223.                   addressBus >= 0x9ac0 && addressBus <=
  224. 0x9adf ||
  225.                   addressBus >= 0x9b60 && addressBus <=
  226. 0x9b7f ||
  227.                   addressBus >= 0x9be0 && addressBus <=
  228. 0x9bff && m1);
  229.  
  230.     int sop1 =    !(addressBus >= 0x9be0 && addressBus <= 0x9bff && m1 ||
  231.                   addressBus >= 0x9ca0 && addressBus <=
  232. 0x9cbf);
  233.  
  234.     int sop2 =    !(addressBus >= 0x00c0 && addressBus <= 0x00df ||
  235.                   addressBus >= 0x9a40 && addressBus <=
  236. 0x9a5f);
  237.  
  238.  
  239.     /* Pal 9c (16r4) */
  240.     int md0  = ByteBit(RAM[addressBus],0);
  241.     int md2  = ByteBit(RAM[addressBus],2);
  242.     int md7  = ByteBit(RAM[addressBus],7);
  243.  
  244.     int d0 =  !( s0 &&  s1 && !md0 ||
  245.                 !s0 &&  s1 &&  md0 ||
  246.                  s0 && !s1 && !md0 ||
  247.                 !s0 && !s1 && !md2);
  248.  
  249.     int d2 =  !( s0 &&  s1 && !md2 ||
  250.                 !s0 &&  s1 && !md2 ||
  251.                  s0 && !s1 &&  md2 ||
  252.                 !s0 && !s1 && !md0);
  253.  
  254.     int d7 =  !( s2 &&  s3  ||
  255.                 !s2 && !md7);
  256.  
  257.     int pb1 = !( sop0 &&  s0 ||
  258.                 !sop0 && !s0);
  259.  
  260.     int ns0 =  ( sop1 &&  s0   ||
  261.                 !sop1 && !s0   ||
  262.                 !sop0 &&  sop1);
  263.  
  264.     int ns1 =  ( sop1 &&  s1 && !pb1 ||
  265.                 !sop1 &&  s1 && !pb1 ||
  266.                  sop1 &&  s1 &&  pb1 ||
  267.                 !sop1 && !s1 &&  pb1 ||
  268.                 !sop0 &&  sop1);
  269.  
  270.     int ns2 =  ( sop0 &&  sop1 &&  s2 ||
  271.                  sop0 && !sop1 &&  s2 ||
  272.                 !sop0 && !sop1 &&  s2 ||
  273.                  sop0 && !sop2);
  274.  
  275.     int ns3 =  ( !md7 );
  276.  
  277. //    DebugPrint("%04x: %02x & %02x | %02x =
  278. %02x",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) |
  279. (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) |
  280. (d2<<2) | (d7<<7));
  281. /*    printf("%04x: %02x & %02x | %02x =
  282. %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) |
  283. (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) |
  284. (d2<<2) | (d7<<7));
  285.     {static int i=0;
  286.     if (i++>100)
  287.     {
  288.         while (getchar()!='\n')
  289.             {}
  290.     }}*/
  291.     {
  292.         int temp= ((int)RAM[addressBus] & 0x7A) | ((d7<<7) |
  293. (d2<<2) | (d0));
  294.  
  295. //        if (Z80_Trace==1)
  296.             if (!used[addressBus])
  297.             {
  298.                 used[addressBus]=1;
  299.                 shadowROM[addressBus] = temp;
  300.                 numberUsed++;
  301.             }
  302.             else
  303.             {
  304.                 if (shadowROM[addressBus] != temp)
  305.                     DebugPrint("Address: %04x
  306. translates to 2 different values!!!! (%02x and
  307. %02x)",addressBus,shadowROM[addressBus],temp);
  308.             }
  309.  
  310.  
  311.         if (Z80_Trace==1)
  312.         {
  313.             static last = 0;
  314.             if (last + 30 <= TickCount()) /* print bnanner if
  315. we havent been called in half a second */
  316.                 printf("m1   sop0 sop1 sop2 pcbe  md7  md2
  317. md0   d7   d2   d0    pb1   s0   s1   s2   s3    ns0  ns1  ns2  ns3\n");
  318.             last = TickCount();
  319.             printf("%-4d %-4d %-4d %-4d %-4d  %-4d %-4d %-4d
  320. %-4d %-4d %-4d  %-4d  %-4d %-4d %-4d %-4d  %-4d %-4d %-4d %-4d     ",
  321.                     m1,  sop0,sop1,sop2,pcbe, md7, md2, md0,
  322. d7,  d2,  d0,   pb1,  s0,  s1,  s2,  s3,   ns0, ns1, ns2, ns3);
  323.             printf("%04x: %02x & %02x | %02x =
  324. %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) |
  325. (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) |
  326. (d2<<2) | (d7<<7));
  327.             Z80_Trace = 1; /* stop it if it was running for a
  328. count */
  329.         }
  330.  
  331.         /* latch new flip flops on rising edge of pcbe */
  332.         if (!pcbe)
  333.         {
  334.             s0 = ns0;
  335.             s1 = ns1;
  336.             s2 = ns2;
  337.             s3 = ns3;
  338.         }
  339.         return temp;
  340.     }
  341.     }
  342. }
  343.  
  344. int Z80_Trace=0;
  345.  
  346. void jr_monitor()
  347. {
  348.     int i;
  349.     int encrypted=0;
  350.     int last_used=-1;
  351.     int unmapped_encrypted=0;
  352.     int unmapped=0;
  353.     printf("statistics: \n");
  354.     printf("  Successfully mapped: %d\n",numberUsed);
  355.     for (i=0;i<0xe000;i=(i==0x4000?0x8000:i+1)) /* skip hole where
  356. hardware and RAM is */
  357.     {
  358.         if (used[i])
  359.         {
  360.             if (shadowROM[i] != RAM[i])
  361.                 encrypted = 1;
  362.             else
  363.                 encrypted = 0;
  364.             last_used = i;
  365.         }
  366.         else
  367.         {
  368.             if (encrypted)
  369.                 unmapped_encrypted++;
  370.             else
  371.                 unmapped++;
  372.         }
  373.     }
  374.     printf("  Non mapped, Probably not encrypted: %d\n",unmapped);
  375.     printf("  Non mapped, but Probably encrypted:
  376. %d\n",unmapped_encrypted);
  377.  
  378.     while (1)
  379.     {
  380.         void write_rom_section(char *prefix,char *suffix,int
  381. start,int end);
  382.         char c;
  383.         printf(" Enter D to Merge mapped and unmapped and dump to
  384. rom file,\n");
  385.         printf(" Enter Q to quit.\n");
  386.         c=tolower(getchar());
  387.         while (getchar()!='\n') {}
  388.         if (c=='q')
  389.             return;
  390.         if (c=='d')
  391.         {
  392.             char line[100],*l;
  393.             int i;
  394.             printf("Enter file prefix (files will be named
  395. 'prefix'.8d 'prefix'.8e, etc.\n");
  396.             gets(line);
  397.             // kill newline:
  398.             for (l=line;*l!='\n' && *l!='\0';l++)
  399.                 {}
  400.             *l = '\0';
  401.  
  402.             write_rom_section(line,".8d",0x0000,0x2000);
  403.             write_rom_section(line,".8e",0x2000,0x4000);
  404.             write_rom_section(line,".8h",0x8000,0xa000);
  405.             write_rom_section(line,".8j",0xa000,0xc000);
  406.             write_rom_section(line,".8k",0xc000,0xe000);
  407.         }
  408.     }
  409. }
  410.  
  411. void write_rom_section(char *prefix,char *suffix,int start,int end)
  412. {
  413.     void *out;
  414.     char file[100];
  415.     int i;
  416.  
  417.     strcpy(file,prefix);
  418.     strcat(file,suffix);
  419.     out = fopen(file,"wb");
  420.     for (i=start;i<end;i++)
  421.         if (used[i])
  422.             putc(shadowROM[i],out);
  423.         else
  424.             putc(RAM[i],out);
  425.     osd_fclose(out);
  426. }
  427. #endif
  428.  
  429. WRITE_HANDLER( jrpacman_interrupt_enable_w )
  430. {
  431.     interrupt_enable = data;
  432. }
  433.  
  434.  
  435.  
  436. /***************************************************************************
  437.  
  438.   Interrupt handler. This function is called at regular intervals
  439.   (determined by IPeriod) by the CPU emulation.
  440.  
  441. ***************************************************************************/
  442.  
  443. static int IntVector = 0xff;    /* Here we store the interrupt vector, if
  444. the code performs */
  445.                         /* an OUT to port $0. Not
  446. all games do it: many use */
  447.                         /* Interrupt Mode 1, which
  448. doesn't use an interrupt vector */
  449.                         /* (see Z80.c for details). */
  450.  
  451. int jrpacman_interrupt(void)
  452. {
  453.     return interrupt();
  454. }
  455.  
  456.  
  457.  
  458. /***************************************************************************
  459.  
  460.   The Pac Man machine uses OUT to port $0 to set the interrupt vector, so
  461.   we have to remember the value passed.
  462.  
  463. ***************************************************************************/
  464. void jrpacman_out(byte Port,byte Value)
  465. {
  466.     /* OUT to port $0 is used to set the interrupt vector */
  467.     if (Port == 0) IntVector = Value;
  468. }
  469.  
  470. #if 0
  471. /****************************************************************************
  472. What follows is the program I used to create the JrPacMan_Table[] array at
  473. the top of this file. It is included here for completeness.
  474. ***************************************************************************/
  475.  
  476.  
  477. // CreateJrDecodeTable.c
  478. //
  479. // Copyright (C) 1997 David Caldwell
  480. // This program is published under the GNU Public License.
  481. //
  482. // Comments, questions to: david@indigita.com
  483.  
  484. #include <stdio.h>
  485.  
  486. typedef unsigned char byte;
  487.  
  488. void CreateJrDecodeTable(byte *x, int length);
  489. void Load(char *name,byte *buffer,int from, int length);
  490.  
  491. byte encrypted[0x10000],decrypted[0x10000];
  492. byte xored[0x10000];
  493. void main()
  494. {
  495.     int i;
  496.  
  497.     Load("jr8d",encrypted,0x0000,0x2000);
  498.     Load("jr8e",encrypted,0x2000,0x2000);
  499.     Load("jr8h",encrypted,0x8000,0x2000);
  500.     Load("jr8j",encrypted,0xA000,0x2000);
  501.     Load("jr8k",encrypted,0xC000,0x2000);
  502.  
  503.     Load("1.8d",decrypted,0x0000,0x2000);
  504.     Load("1.8e",decrypted,0x2000,0x2000);
  505.     Load("1.8h",decrypted,0x8000,0x2000);
  506.     Load("1.8j",decrypted,0xA000,0x2000);
  507.     Load("1.8k",decrypted,0xC000,0x2000);
  508.  
  509.     for (i=0;i<0x10000;i++)
  510.         xored[i] = encrypted[i] ^ decrypted[i];
  511.  
  512.     CreateJrDecodeTable(xored,0x10000);
  513. }
  514.  
  515. void Load(char *name,byte *buffer,int from, int length)
  516. {
  517.     void *file = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0);
  518.     if (!file)
  519.         return;
  520.     while (length--)
  521.         buffer[from++]=fgetc(file);
  522.     osd_fclose(file);
  523. }
  524.  
  525. void CreateJrDecodeTable(byte *x, int length)
  526. {
  527.     int i=0;
  528.     byte last = 0;
  529.     int count = 0;
  530.  
  531.     printf(    "struct {\n"
  532.             "    int count;\n"
  533.             "    int value;\n"
  534.             "} Jr_PacManTable[] = {\n");
  535.  
  536.     goto first;
  537.  
  538.     for (i=0;i<length;i++)
  539.     {
  540.         if (x[i] != last)
  541.         {
  542.             printf("    { 0x%04X, 0x%02X },\n",count,last);
  543.             count = 0;
  544.         }
  545. first:
  546.         last = x[i];
  547.         count++;
  548.     }
  549.  
  550.     printf("    { 0x%04X, 0x%02X },\n",count,last);
  551.     printf(    "    { 0,0 }\n"
  552.             "};\n");
  553. }
  554. #endif
  555.